package com.nj9you.sdk.framework;

import android.app.Activity;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Handler;
import android.preference.PreferenceManager;
import android.text.TextUtils;

import com.nj9you.sdk.dlg.OrderDetailDialog;
import com.nj9you.sdk.dlg.PayListShow;
import com.nj9you.sdk.listener.PayCallback;
import com.nj9you.sdk.params.PayParams;
import com.nj9you.sdk.params.User;
import com.nj9you.sdk.pay.Alipay;
import com.nj9you.sdk.pay.IPay;
import com.nj9you.sdk.pay.JubaoPay;
import com.nj9you.sdk.pay.ShenzhouPay;
import com.nj9you.sdk.pay.SwiftPay;
import com.nj9you.sdk.pay.WechatPay;
import com.nj9you.sdk.pay.YeePay;
import com.nj9you.sdk.request.IPayRequest;
import com.nj9you.sdk.request.PayRequestImpl;
import com.nj9you.sdk.user.UserManager;
import com.nj9you.sdk.utils.Log;
import com.nj9you.sdk.utils.Utils;

import java.util.ArrayList;
import java.util.List;

/**
 * 支付相关功能
 */
public class PayModule implements IPayFunction, IUserPay {

    private final Context mContext;
    private List<IPay> payList = new ArrayList<IPay>();
    private PayParams mPayParams;
    private PayCallback mPayCallback;
    private IPayRequest mPayRequest;
    private Handler mHandler;
    // 订单展示对话框
    private OrderDetailDialog mOrderDetailDialog;
    private volatile boolean mPaying = false;

    public PayModule(Context context) {
        if (!(context instanceof Activity)) {
            throw new IllegalArgumentException("Context must be an Activity");
        }
        mContext = context;
        mHandler = new Handler(context.getMainLooper());
        mPayRequest = new PayRequestImpl(context);
        initPayList();
    }

    private void initPayList() {
        new Thread() {
            public void run() {
                IPay iPay = null;

                iPay = new Alipay();
                iPay.init(mContext, PayModule.this);
                if (iPay.checkPayAvailable()) {
                    payList.add(iPay);
                }

                iPay = new WechatPay();
                iPay.init(mContext, PayModule.this);
                if (iPay.checkPayAvailable()) {
                    payList.add(iPay);
                }

                iPay = new ShenzhouPay();
                iPay.init(mContext, PayModule.this);
                if (iPay.checkPayAvailable()) {
                    payList.add(iPay);
                }

                iPay = new SwiftPay();
                iPay.init(mContext, PayModule.this);
                if (iPay.checkPayAvailable()) {
                    payList.add(iPay);
                }

                iPay = new YeePay();
                iPay.init(mContext, PayModule.this);
                if (iPay.checkPayAvailable()) {
                    payList.add(iPay);
                }

                iPay = new JubaoPay();
                iPay.init(mContext, PayModule.this);
                if (iPay.checkPayAvailable()) {
                    payList.add(iPay);
                }
            }
        }.start();
    }

    /**
     * 检测支付参数的合法性
     * @param payParams
     * @return
     */
    private boolean checkPayParams(PayParams payParams) {
        if (TextUtils.isEmpty(payParams.getSubject())
                || payParams.getSubject().length() > 100) {
            String desc = mContext.getString(Utils.getStringId(mContext, "jy_pay_error_subject"));
            notifyPayResult(PayResult.PAY_FAILURE, desc, null);
            return false;
        }
        if (TextUtils.isEmpty(payParams.getPrice())
                || !TextUtils.isDigitsOnly(payParams.getPrice())
                || Utils.parseStringToInt(payParams.getPrice()) <= 0) {
            String desc = mContext.getString(Utils.getStringId(mContext, "jy_pay_error_price"));
            notifyPayResult(PayResult.PAY_FAILURE, desc, null);
            return false;
        }
        if (TextUtils.isEmpty(payParams.getOrder())
                || payParams.getOrder().length() > 32) {
            String desc = mContext.getString(Utils.getStringId(mContext, "jy_pay_error_order"));
            notifyPayResult(PayResult.PAY_FAILURE, desc, null);
            return false;
        }
        if (!TextUtils.isEmpty(payParams.getBody()) && payParams.getBody().length() > 128) {
            String desc = mContext.getString(Utils.getStringId(mContext, "jy_pay_error_body"));
            notifyPayResult(PayResult.PAY_FAILURE, desc, null);
            return false;
        }
        if (!TextUtils.isEmpty(payParams.getServer()) && payParams.getServer().length() > 20) {
            String desc = mContext.getString(Utils.getStringId(mContext, "jy_pay_error_server"));
            notifyPayResult(PayResult.PAY_FAILURE, desc, null);
            return false;
        }
        if (!TextUtils.isEmpty(payParams.getAttach()) && payParams.getAttach().length() > 200) {
            String desc = mContext.getString(Utils.getStringId(mContext, "jy_pay_error_attach"));
            notifyPayResult(PayResult.PAY_FAILURE, desc, null);
            return false;
        }
        if (TextUtils.isEmpty(payParams.getItemid()) || payParams.getItemid().length() > 30) {
            String desc = mContext.getString(Utils.getStringId(mContext, "jy_pay_error_itemid"));
            notifyPayResult(PayResult.PAY_FAILURE, desc, null);
            return false;
        }
        return true;
    }

    @Override
    public void pay(PayParams payParams, PayCallback callback) {
        if (payParams == null) {
            throw new IllegalArgumentException("PayParams must be not null");
        }
        if (callback == null) {
            throw new IllegalArgumentException("PayCallback must be not null");
        }

        // 检测是否有支付在进行中
        if (checkPaying(callback)) {
            return;
        }

        mPayParams = payParams;
        mPayCallback = callback;
        // 检测用户登录
        boolean checkUserLogin = checkLoginUser();
        if (!checkUserLogin) {
            String desc = mContext.getString(Utils.getStringId(mContext, "jy_unlogin_user"));
            notifyPayResult(PayResult.PAY_FAILURE, desc, null);
            return;
        }
        // 检测支付参数
        boolean checkResult = checkPayParams(payParams);
        if (!checkResult) {
            return;
        }
        List<IPay> payList = getPayList();
        if (payList != null && payList.size() > 0) {
            // 强制调用payInternal函数，showPayList函数丢弃使用
            if (payList.size() == 1 || true) {
                payInternal(payParams, getDefaultPay(payList), payList);
            } else {
                showPayList(payParams, payList);
            }
        } else {
            // 未找到支付模块
            String desc = mContext.getString(Utils.getStringId(mContext, "jy_miss_paymodule"));
            notifyPayResult(PayResult.PAY_FAILURE, desc, null);
        }
    }

    /**
     * 获取默认选择的支付
     * @param payList
     * @return
     */
    private IPay getDefaultPay(List<IPay> payList) {
        if (payList == null || payList.isEmpty()) {
            return null;
        }
        IPay defaultPay = payList.get(0);
        int lastPayType = PreferenceManager.getDefaultSharedPreferences(mContext).getInt("last_pay_type", -1);
        if (lastPayType > -1) {
            for (IPay ipay : payList) {
                if (lastPayType == ipay.getPayType()) {
                    defaultPay = ipay;
                    break;
                }
            }
        }
        return defaultPay;
    }

    /**
     * 检查登录用户
     *
     * @return
     */
    private boolean checkLoginUser() {
        User user = UserManager.get(mContext).loadCurrentUser();
        if (user != null && !TextUtils.isEmpty(user.getUsername())) {
            return true;
        }
        return false;
    }

    /**
     * 检查是否有支付在进行中
     * @param callback
     * @return true 有支付正在进行，false 没有支付在进行
     */
    private boolean checkPaying(final PayCallback callback) {
        Log.d(Log.TAG, "mPaying : " + mPaying);
        if (mPaying) { // 通知用户支付正在进行中
            final String desc = mContext.getString(Utils.getStringId(mContext, "jy_pay_ongoing"));
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    // 回调支付通知
                    if (callback != null) {
                        callback.onPayResult(PayResult.PAY_ONGOING, desc, mPayParams);
                    }
                }
            });
            return true;
        }
        // 设置开始支付标志
        mPaying = true;
        return false;
    }

    @Override
    public void notifyPayResult(final int code, String desc, final IPay iPay) {
        // 支付结束标识
        mPaying = false;
        // TODO:加上支付方式,此为调试代码
        desc = "" + (iPay != null ? iPay.getPayName() + " : " : "") + desc;
        notifyPayResultAndDismissOrderDetailDialog(code, desc, iPay);
    }

    /**
     * 通知支付结果，并关闭订单对话框
     *
     * @param code
     * @param desc
     * @param iPay
     */
    private void notifyPayResultAndDismissOrderDetailDialog(final int code,
                                                            final String desc, final IPay iPay) {
        // 订单对话框还未关闭时，延迟关闭订单对话框和发送支付通知
        boolean delay = mOrderDetailDialog != null && mOrderDetailDialog.isShowing();
        // 此处的延迟，是由于横竖屏切换带来视觉上的异常体验
        mHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                // 关闭订单对话框
                dismissOrderDetail();
                // 回调支付通知
                if (mPayCallback != null) {
                    mPayCallback.onPayResult(code, desc, mPayParams);
                }
            }
        }, delay ? 1000 : 0);
    }

    @Override
    public IPayRequest getPayRequest() {
        return mPayRequest;
    }

    /**
     * 显示支付列表
     *
     * @param payParams
     * @param payList
     * @deprecated 旧的支付类型选择对话框
     */
    private void showPayList(final PayParams payParams, final List<IPay> payList) {
        PayListShow payListShow = new PayListShow(mContext);
        payListShow.setOnPayShowListener(new PayListShow.OnPayListListener() {
            @Override
            public void onPaySelected(IPay ipay) {
                payInternal(payParams, ipay, payList);
            }

            @Override
            public void onCancel() {
                String desc = mContext.getString(Utils.getStringId(mContext, "jy_cancel_pay"));
                notifyPayResult(PayResult.PAY_CANCEL, desc, null);
            }
        });
        payListShow.showPayList(payList);
    }

    /**
     * 优化订单参数，显示订单详情
     *
     * @param payParams
     * @param iPay
     */
    private void payInternal(PayParams payParams, IPay iPay, final List<IPay> payList) {
        showOrderDetail(payParams, iPay, payList);
    }

    private void showOrderDetail(final PayParams payParams, final IPay iPay, final List<IPay> payList) {
        int theme = Utils.isFullScreen(mContext) ? android.R.style.Theme_NoTitleBar_Fullscreen
                : android.R.style.Theme_NoTitleBar;
        mOrderDetailDialog = new OrderDetailDialog(mContext, payParams, iPay, payList, theme);
        mOrderDetailDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
            @Override
            public void onCancel(DialogInterface dialog) {
                mOrderDetailDialog = null;
                String desc = mContext.getString(Utils.getStringId(mContext, "jy_cancel_pay"));
                notifyPayResult(PayResult.PAY_CANCEL, desc, iPay);
            }
        });
        mOrderDetailDialog.setOnConfirmPayListener(new OrderDetailDialog.OnConfirmPayListener() {
            @Override
            public void onConfirmPay(IPay iPay, PayParams payParams) {
                if (iPay != null) {
                    iPay.pay(payParams);
                    saveLastPayType(iPay);
                } else {
                    String desc = mContext.getString(Utils.getStringId(mContext, "jy_unknown"));
                    notifyPayResult(PayResult.PAY_FAILURE, desc, iPay);
                }
            }
        });
        mOrderDetailDialog.show();
    }

    /**
     * 保存支付
     * @param pay
     */
    private void saveLastPayType(IPay pay) {
        if (pay == null) {
            return;
        }
        PreferenceManager.getDefaultSharedPreferences(mContext).edit().putInt("last_pay_type", pay.getPayType()).commit();
    }

    /**
     * 关闭订单对话框
     */
    private void dismissOrderDetail() {
        if (mOrderDetailDialog != null && mOrderDetailDialog.isShowing()) {
            mOrderDetailDialog.dismiss();
            mOrderDetailDialog = null;
        }
    }

    @Override
    public List<IPay> getPayList() {
        return payList;
    }
}
